package cbbx_sm.decision_maker;

import java.util.Hashtable;
import java.util.List;
import java.util.Vector;

import cbbx_sm.decision_maker.search.DynamicProgrammingLookahead;
import cbbx_sm.decision_maker.search.Schedules;
import cbbx_sm.probabilistic_model.Cluster;
import cbbx_sm.probabilistic_model.Prediction;
import cbbx_sm.utils.ExperimentManager;

/**
 * Based on a pre-computed table of best actions the scheduler decides where to zoom.
 * The best actions are computed with a look ahead for highest expected utility.
 * 
 * @author Ronen Vaisenberg - University of California, Irvine
 *
 */
public class LookAheadDecisionMaker implements IDecisionMaker {
	
	private List<String> cameraIds;
	private Hashtable<String, Cluster> clusterIndex;
	private Hashtable<String,DynamicProgrammingLookahead> table;
	private double utilityZoom;
	private double utilityUP;
	private double delta;
	private double numberOfStates;
	private int numberOfTimeStampsLookAhead;
	protected boolean recordNeededStates;

	
	public LookAheadDecisionMaker(List<String> cameraIds,
			Hashtable<String,DynamicProgrammingLookahead> table, 
			Hashtable<String, Cluster> clusterIndex,
			double utilityZoom, double utilityUP, double delta, int numberOfStates, int numberOfTimeStampsLookAhead){
		this.cameraIds = cameraIds;
		this.table = table;
		this.clusterIndex = clusterIndex;
		this.utilityZoom = utilityZoom;
		this.utilityUP = utilityUP;
		this.delta = delta;
		this.numberOfStates = numberOfStates;
		this.numberOfTimeStampsLookAhead = numberOfTimeStampsLookAhead;
		this.recordNeededStates = false;
	}
	
	@Override
	public Decision makeDecision(Prediction currentPrediction){

		List<CameraConfiguration> confs = new Vector<CameraConfiguration>();
		
		//For each camera separately compute the action based on its probabilities.
		for (String cam: cameraIds){
			String bestAction = table.get(cam).getBestAction(currentPrediction.getClusterProbabilities(), recordNeededStates);			
			if (bestAction.compareTo(Schedules.UP)!=0){
				confs.add(new CameraConfiguration(cam, clusterIndex.get(bestAction)));
			}
		}
		
		Decision decision = new Decision(confs);

		return decision;
	}

	@Override
	public String toString(){
		return String.format("%s%s_%d_%.1f_%.1f_%f_%f_%d",
				this.getClass().getSimpleName(), ExperimentManager.usePreComputedGrid, cameraIds.size(), utilityZoom, utilityUP, delta, numberOfStates, numberOfTimeStampsLookAhead);
	}
}
